package com.kili.picture.context;

import com.kili.picture.context.exception.DataException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * @author
 */
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(IllegalArgumentException.class)
    public Result handleIllegalArgumentException(IllegalArgumentException e) {
        logger.error("IllegalArgumentException ", e);
        return Result.of(ResultStatus.ARGUMENT_EXCEPTION.getValue(), e.getMessage());
    }

    @ExceptionHandler(DataException.class)
    public Result handleDataException(DataException e) {
        logger.error("DataException ", e);
        return Result.of(ResultStatus.DATA_EXCEPTION.getValue(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        Result result = new Result();

        // 已知异常
        if (e instanceof MethodArgumentNotValidException) {
            handleArgumentException(result, ((MethodArgumentNotValidException) e).getBindingResult());
        } else if (e instanceof BindException) {
            handleArgumentException(result, ((BindException) e).getBindingResult());
        } else {
            // 未知异常是应该重点关注的，这里可以做其他操作，如通知邮件，单独写到某个文件等等。
            logger.error(" error: ", e);
            return Result.of(ResultStatus.INTERNAL_SERVER_ERROR);
        }
        return result;
    }

    private void handleArgumentException(Result result, BindingResult bindingResult) {
        result.setResultStatus(ResultStatus.ARGUMENT_EXCEPTION);
        List<ObjectError> allErrors = bindingResult.getAllErrors();
        if (allErrors != null && allErrors.size() > 0) {
            StringBuffer data = new StringBuffer();

            for (int i = 0, j = allErrors.size(); i < j; i++) {
                data.append((i + 1) + ".");
                data.append(allErrors.get(i).getDefaultMessage());
                data.append(". ");
            }

            result.setData(data.toString());
        }
    }

}